再更進一步提取更多函式之前,我們先原地調整一下,「深呼吸,慢吐氣;吸氣~吐氣~。你做的很好。」
我們首先看最外層結構的部分,參考下圖:
▼最外層結構 |
---|
在 jq 中,generator 是一個產生多個輸出的過濾器。換句話說,它會針對單個輸入產生多個結果,而不是一次產生一個結果。當我們使用像 .[]
這樣的過濾器來處理一個陣列時,這就是一個 generator,它會針對陣列中的每個元素依次產生輸出。
常見用途:
.[]
會將陣列中的每個元素作為單獨的輸出。,
讓多個結果能從一個輸入生成。split()
生成多個子字串。在認識 generator 概念之後,我們目前jq程式的最外層結構有沒有使用到 generator 呢? 🤓
編號 | 內容 | generator |
---|---|---|
1 | 定義 separate(f) 函式 | split() |
2 | 將各個輸入陣列元素儲存為變數 | 沒有(使用slurp參數的結果) |
3 | 組合標題陣列與每一行 AnalysisData | , 和.[] |
4 | 以 TSV 格式輸出 | 沒有 |
上面整理過的編號,除了1是定義函式之外, 2 的產出(變數)是 3 的輸入,3 的產出(標題+資料)是 4 的輸入,4 產出就是最終的輸出。由此可見,我們最主要的資料處理操作,還是針對編號 3;而且從最外層的結構,我們就可以觀察到內容結果會是一行標題列[標題的固定字串]
加上多行AnalysisData[AnalysisData][]
的結果。
▼ 取得 Analysis 結構 |
---|
編號 | 內容 | generator |
---|---|---|
1 | 颱風陣列 | .[] |
2 | 篩選,只看山陀兒的資料 | 沒有 |
3 | 山陀兒路徑資料中的最近五筆 AnalysisData | .[] |
4 | 要顯示的資料內容 | 詳看下段 |
仔細觀察,在這段取得 Analysis 結構的內容當中,第一次使用 generator .[]
是在 select()
之前(1 的產出是 2 的輸入,要先逐一看過颱風資料,才能從中篩選名稱是山陀兒的那一筆);第二次使用 generator .[]
,則就是要準備逐筆整理 AnalysisData 了(3 的產出是 4 的輸入,要先逐一看過每小時路徑的資料,才有辦法選到路徑的時間與方向)。
[
.fixTime[0:13],
separate(.coordinate)[0],
separate(.coordinate)[1],
.pressure,
((.maxWindSpeed|tonumber) as $speed|$wind[]|select($speed>=.min and $speed<.max)|.level),
((.maxGustSpeed|tonumber) as $speed|$wind[]|select($speed>=.min and $speed<.max)|.level),
$direction[.movingDirection],
.movingPrediction[0].value
]
輸出字串陣列:因為在一開始實作的時候,我們的目標朝向最終能於 terminal 以 TSV 格式顯示;所以這個陣列基本上就是由 generator ,
將各個字串組合而成。如果目標是輸出 json 格式,就會是不同的作法了。
座標:使用了最外層定義的 separate 函式。因為 separate 函式有使用到 generator split()
生成多個子字串,所以這邊可以用索引[0]和[1]取得指定的字串。
風速:
風速這個整理的過程使用了兩次,很明顯之後可以再提取成函式💡。
首先轉型為數值 $speed
,使用 generator .[]
將 $wind
變數陣列逐一取出,再透過 $speed
符合的風速範圍篩選,以 .level
顯示結果。
((.maxWindSpeed|tonumber) as $speed|
$wind[]|
select($speed>=.min and $speed<.max)|
.level)
又一次,使用 generator .[]
是在 select()
之前。
今天我們認識了 generator 的概念,並且重新再回顧一次這段處理山陀兒颱風的程式碼。剛開始使用 jq 時,看到 generator 的介紹,會有一種 "我看到了,又好像沒看到" 的情況。使用一陣子之後,就會恍然大悟,jq 語法的簡潔,似乎和 generator 尤其是.[]
有著密不可分的關係! 👓
用一疊撲克牌來比喻陣列的話, generator .[]
就像是把原本疊成一疊的撲克牌展開,擺成一張一張的供人挑選。
感謝自己,今天也很認真學習。😊